/*
 * Mat4.h
 *
 *  Created on: 29.09.2009
 *      Author: Christoph Caks
 */

#ifndef MAT4_H_
#define MAT4_H_

#include "System.h"
#include "Math.h"
#include "types/Vec4.h"

namespace mehari {
namespace common {

template < typename Real >
class Mat4 {
public:
	Mat4();
	Mat4( 	const Real r00, const Real r01, const Real r02, const Real r03,
			const Real r10, const Real r11, const Real r12, const Real r13,
			const Real r20, const Real r21, const Real r22, const Real r23,
			const Real r30, const Real r31, const Real r32, const Real r33 );
	Mat4( const Real matrix[16] );
	Mat4( const Mat4& m4 );
	~Mat4();

	void setZero();
	void setIdentity();

	// access
	const Real* operator[] ( int iRow ) const;
	Real* operator [] ( int iRow );
	Real operator () ( int iRow, int iCol ) const;
	Real& operator () ( int iRow, int ICol );

	void setRow( int iRow, const Vec4<Real>& v4Val );
	void setCol( int iCol, const Vec4<Real>& v4Val );

	Vec4<Real> getRow( int iRow ) const;
	Vec4<Real> getCol( int iCol ) const;

	operator float* () { return &data; }
	const Real* getData() const { return &data[0]; }


	// assignment
	Mat4<Real>& operator = ( const Mat4<Real>& mRhs );

	// arithmetic operations
	Mat4<Real> operator + ( const Mat4<Real>& m4Rhs ) const;
	Mat4<Real> operator - ( const Mat4<Real>& m4Rhs ) const;
	Mat4<Real> operator * ( const Real rRhs ) const;
	Mat4<Real> operator / ( const Real rRhs ) const;
	Mat4<Real> operator * ( const Mat4<Real>& m4Rhs ) const;

	Mat4<Real> operator += ( const Mat4<Real>& m4Rhs );
	Mat4<Real> operator -= ( const Mat4<Real>& m4Rhs );
	Mat4<Real> operator *= ( const Real rRhs );
	Mat4<Real> operator /= ( const Real rRhs );
	Mat4<Real> operator *= ( const Mat4<Real>& m4Rhs );

	// comparison operations
	bool operator == ( const Mat4<Real>& m4Rhs ) const;
	bool operator != ( const Mat4<Real>& m4Rhs ) const;
	bool operator <  ( const Mat4<Real>& m4Rhs ) const;
	bool operator <= ( const Mat4<Real>& m4Rhs ) const;
	bool operator >  ( const Mat4<Real>& m4Rhs ) const;
	bool operator >= ( const Mat4<Real>& m4Rhs ) const;

	// geometric operations
	Mat4<Real> transpose() const;
	Mat4<Real> inverse() const;
	Mat4<Real> adjoint() const;
	Real determinant() const;

	// Mat4 * Vec3
	Vec4<Real> operator * ( const Vec4<Real>& v4Rhs ) const;

private:
	/**
	 * holds the data
	 *  0  1  2  3
	 *  4  5  6  7
	 *  8  9 10 11
	 * 12 13 14 15
	 */
	Real data[16];
};

#include "../../src/types/Mat4.cpp.inl"

typedef Mat4<float> Mat4f;
typedef Mat4<double> Mat4d;

} // namespace common
} // namespace mehari



#endif /* MAT4_H_ */
